"""
项目生成器核心模块
负责生成标准化的Python项目目录结构
"""

from pathlib import Path
from typing import Dict, List, Optional, Any
from loguru import logger
from rich.console import Console
from rich.progress import track

from .config import ProjectConfig
from .templates import TemplateManager


class ProjectGenerator:
    """Python项目结构生成器"""
    
    def __init__(self, config: Optional[ProjectConfig] = None):
        """
        初始化项目生成器
        
        Args:
            config: 项目配置对象，如果为None则使用默认配置
        """
        self.config = config or ProjectConfig()
        self.template_manager = TemplateManager()
        self.console = Console()
        
        # 配置日志
        logger.remove()
        logger.add(
            "logs/generator.log",
            rotation="5 MB",
            retention="30 days",
            level="INFO",
            format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
        )
    
    def generate_project(
        self, 
        project_name: str, 
        target_dir: str = ".",
        project_type: str = "fastapi",
        **kwargs
    ) -> bool:
        """
        生成新的Python项目
        
        Args:
            project_name: 项目名称
            target_dir: 目标目录
            project_type: 项目类型 (fastapi, fastmcp)
            **kwargs: 其他配置参数
            
        Returns:
            bool: 生成是否成功
        """
        try:
            logger.info(f"开始生成项目: {project_name}")
            self.console.print(f"[bold green]正在生成项目: {project_name}[/bold green]")
            
            # 创建项目根目录
            project_path = Path(target_dir) / project_name
            if project_path.exists():
                self.console.print(f"[bold red]错误: 目录 {project_path} 已存在[/bold red]")
                return False
            
            project_path.mkdir(parents=True, exist_ok=True)
            logger.info(f"创建项目目录: {project_path}")
            
            # 更新配置
            self.config.update({
                "project_name": project_name,
                "project_type": project_type,
                "target_dir": str(project_path),
                **kwargs
            })
            
            # 生成目录结构
            self._create_directory_structure(project_path)
            
            # 生成配置文件
            self._generate_config_files(project_path)
            
            # 生成代码文件
            self._generate_source_files(project_path)
            
            # 生成文档文件
            self._generate_documentation(project_path)
            
            # 初始化git仓库
            if self.config.get("init_git", True):
                self._init_git_repository(project_path)
            
            # 初始化uv项目
            if self.config.get("use_uv", True):
                self._init_uv_project(project_path)
            
            self.console.print(f"[bold green]✅ 项目 {project_name} 生成成功![/bold green]")
            logger.info(f"项目生成完成: {project_path}")
            return True
            
        except Exception as e:
            logger.error(f"项目生成失败: {str(e)}")
            self.console.print(f"[bold red]❌ 项目生成失败: {str(e)}[/bold red]")
            return False
    
    def _create_directory_structure(self, project_path: Path) -> None:
        """创建项目目录结构"""
        
        # 标准目录结构
        directories = [
            "app",
            "tests",
            "docs", 
            "logs",
            "docker",
        ]
        
        # 根据项目类型添加特定目录
        project_type = self.config.get("project_type", "fastapi")
        if project_type == "fastapi":
            directories.extend([
                "app/api",
                "app/models",
                "app/utils",
                "app/kit",  # 添加kit目录
                "config",
            ])
        elif project_type == "fastmcp":
            directories.extend([
                "app/mcp",
                "app/tools",
                "app/utils",
                "app/kit",  # 添加kit目录
                "config",
            ])
        
        # 创建目录
        for directory in track(directories, description="创建目录结构..."):
            dir_path = project_path / directory
            dir_path.mkdir(parents=True, exist_ok=True)
            logger.debug(f"创建目录: {dir_path}")
            
            # 创建__init__.py文件（对于Python包目录）
            if (directory.startswith("app/") and not directory.endswith("static")) or directory in ["config", "app/utils", "app/kit"]:
                init_file = dir_path / "__init__.py"
                init_file.write_text('"""Package initialization file."""\n')
    
    def _generate_config_files(self, project_path: Path) -> None:
        """生成配置文件"""
        
        configs = {
            "pyproject.toml": self.template_manager.get_pyproject_template(self.config),
            ".gitignore": self.template_manager.get_gitignore_template(),
            ".env.example": self.template_manager.get_env_template(),
            "docker/docker-compose.yml": self.template_manager.get_docker_compose_template(self.config),
            "docker/Dockerfile": self.template_manager.get_dockerfile_template(self.config),
            "docker/.dockerignore": self.template_manager.get_dockerfile_template(self.config),
        }
        
        for filename, content in track(configs.items(), description="生成配置文件..."):
            file_path = project_path / filename
            file_path.parent.mkdir(parents=True, exist_ok=True)
            file_path.write_text(content, encoding="utf-8")
            logger.debug(f"生成配置文件: {file_path}")
    
    def _generate_source_files(self, project_path: Path) -> None:
        """生成源代码文件"""
        
        project_type = self.config.get("project_type", "fastapi")
        
        if project_type == "fastapi":
            self._generate_fastapi_files(project_path)
        elif project_type == "fastmcp":
            self._generate_fastmcp_files(project_path)
        else:
            self._generate_fastapi_files(project_path)  # 默认使用fastapi    
    def _generate_fastapi_files(self, project_path: Path) -> None:
        """生成FastAPI项目文件"""
        
        files = {
            "main.py": self.template_manager.get_fastapi_main_template(self.config),
            "app/__init__.py": f'"""Source package initialization."""\n__version__ = "{self.config.version}"\n',
            "app/api/__init__.py": '"""API package initialization."""\n',
            "app/api/router.py": self.template_manager.get_fastapi_router_template(),
            "config/__init__.py": '"""Config package initialization."""\n', 
            "config/sys_config.py": self.template_manager.get_fastapi_config_template(),
            "app/models/__init__.py": '"""Models package initialization."""\n',
            "app/models/base.py": self.template_manager.get_pydantic_models_template(),
            "app/utils/__init__.py": '"""Utils package initialization."""\n',
            "app/utils/helpers.py": self.template_manager.get_utils_template(),
        }
        
        for filename, content in track(files.items(), description="生成FastAPI代码文件..."):
            file_path = project_path / filename
            file_path.write_text(content, encoding="utf-8")
            logger.debug(f"生成代码文件: {file_path}")
            
        # 复制config和kit目录下的文件
        self._copy_config_and_kit_files(project_path)
    
    def _generate_fastmcp_files(self, project_path: Path) -> None:
        """生成FastMCP项目文件"""
        
        files = {
            "main.py": self.template_manager.get_fastmcp_main_template(self.config),
            "app/__init__.py": f'"""Source package initialization."""\n__version__ = "{self.config.version}"\n',
            "app/mcp/__init__.py": '"""MCP package initialization."""\n',
            "app/mcp/server.py": self.template_manager.get_fastmcp_server_template(),
            "app/tools/__init__.py": '"""Tools package initialization."""\n',
            "app/tools/example_tools.py": self.template_manager.get_fastmcp_tools_template(),
            "config/__init__.py": '"""Config package initialization."""\n',
            "config/sys_config.py": self.template_manager.get_fastapi_config_template(),
            "app/utils/__init__.py": '"""Utils package initialization."""\n',
            "app/utils/helpers.py": self.template_manager.get_utils_template(),
        }
        
        for filename, content in track(files.items(), description="生成FastMCP代码文件..."):
            file_path = project_path / filename
            file_path.write_text(content, encoding="utf-8")
            logger.debug(f"生成代码文件: {file_path}")
            
        # 复制config和kit目录下的文件
        self._copy_config_and_kit_files(project_path)
    
    def _generate_documentation(self, project_path: Path) -> None:
        """生成文档文件"""
        
        docs = {
            "README.md": self.template_manager.get_readme_template(self.config),
            "CHANGELOG.md": self.template_manager.get_changelog_template(),
            "CONTRIBUTING.md": self.template_manager.get_contributing_template(),
            "LICENSE": self.template_manager.get_license_template(),
            "docs/index.md": self.template_manager.get_docs_index_template(self.config),
        }
        
        for filename, content in track(docs.items(), description="生成文档文件..."):
            file_path = project_path / filename
            file_path.write_text(content, encoding="utf-8")
            logger.debug(f"生成文档文件: {file_path}")
    
    def _init_git_repository(self, project_path: Path) -> None:
        """初始化Git仓库"""
        try:
            import subprocess
            
            # 初始化git仓库
            subprocess.run(
                ["git", "init"], 
                cwd=project_path, 
                check=True, 
                capture_output=True
            )
            
            # 添加所有文件
            subprocess.run(
                ["git", "add", "."], 
                cwd=project_path, 
                check=True, 
                capture_output=True
            )
            
            # 初始提交
            subprocess.run(
                ["git", "commit", "-m", "Initial commit"], 
                cwd=project_path, 
                check=True, 
                capture_output=True
            )
            
            logger.info("Git仓库初始化完成")
            self.console.print("[green]✅ Git仓库初始化完成[/green]")
            
        except Exception as e:
            logger.warning(f"Git仓库初始化失败: {str(e)}")
            self.console.print(f"[yellow]⚠️ Git仓库初始化失败: {str(e)}[/yellow]")
    
    def _init_uv_project(self, project_path: Path) -> None:
        """初始化uv项目"""
        try:
            import subprocess
            
            # 检查uv是否安装
            subprocess.run(
                ["uv", "--version"], 
                check=True, 
                capture_output=True
            )
            
            # 初始化uv项目
            subprocess.run(
                ["uv", "init", "--no-readme"], 
                cwd=project_path, 
                check=True, 
                capture_output=True
            )
            
            logger.info("uv项目初始化完成")
            self.console.print("[green]✅ uv项目初始化完成[/green]")
            
        except FileNotFoundError:
            logger.warning("uv未安装，跳过uv项目初始化")
            self.console.print("[yellow]⚠️ uv未安装，请手动安装依赖[/yellow]")
        except Exception as e:
            logger.warning(f"uv项目初始化失败: {str(e)}")
            self.console.print(f"[yellow]⚠️ uv项目初始化失败: {str(e)}[/yellow]")
    
    def list_templates(self) -> List[str]:
        """列出可用的项目模板"""
        return self.template_manager.list_templates()
    
    def get_template_info(self, template_name: str) -> Dict[str, Any]:
        """获取模板信息"""
        return self.template_manager.get_template_info(template_name)
    
    def _copy_config_and_kit_files(self, project_path: Path) -> None:
        """复制config和kit目录下的文件到生成的项目中"""
        import shutil
        from pathlib import Path as StdPath
        
        # 获取当前工作目录（SDP-PY项目根目录）
        sdp_root = StdPath(__file__).parent.parent
        
        # 复制config目录下的所有文件到项目config目录
        config_src = sdp_root / "config"
        config_dst = project_path / "config"
        if config_src.exists():
            for file_path in config_src.iterdir():
                if file_path.is_file():
                    shutil.copy2(file_path, config_dst)
                    logger.debug(f"复制配置文件: {file_path.name}")
        
        # 复制kit目录下的所有文件到项目app/kit目录
        kit_src = sdp_root / "kit"
        kit_dst = project_path / "app" / "kit"
        if kit_src.exists():
            for file_path in kit_src.iterdir():
                if file_path.is_file():
                    shutil.copy2(file_path, kit_dst)
                    logger.debug(f"复制工具文件: {file_path.name}")
